\ProvidesPackage{rulercompass}
\usepackage{alphalph}
\usetikzlibrary{intersections,calc}

\newif\ifrc@draft
\newif\ifrc@beamer
\newif\ifrc@fliparc

\@ifclassloaded{beamer}{%
	\rc@beamertrue
}{}

\DeclareOption{draft}{%
	\rc@drafttrue
}

\DeclareOption{beamer}{%
	\rc@beamertrue
}

\ProcessOptions

\newcounter{pointlabels}
\setcounter{pointlabels}{0}
\resetcounteronoverlays{pointlabels}

\ifrc@beamer
	\tikzset{
		onslide/.code args={<#1>#2}{%
				\only<#1>{\pgfkeysalso{#2}}%
			},
		alt/.code args={<#1>#2#3}{%
				\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}%
			},
		alt if exist/.code args={#1#2#3}{%
				\@ifundefined{path@#1}{%
					\pgfkeysalso{#2}%
				}{
					\alt<.-\csname path@#1\endcsname>{%
						\pgfkeysalso{#2}%
					}{
						\pgfkeysalso{#3}%
					}%
				}%
			},
		intersection/save/.code={%
				\begingroup
				\only<.>{%
					\tikz@intersect@path@names@parse#1\tikz@stop
					\protected@write\pgfutil@auxout{}{%
						\string\global\string\@namedef{path@\tikz@intersect@path@a}{\the\beamer@slideinframe}%
						\string\global\string\@namedef{path@\tikz@intersect@path@b}{\the\beamer@slideinframe}%
					}%
				}%
				\endgroup
			}
	}

	\newcommand<>\compass[3][]{%
		\draw#4[#1,ruler compass/compass={#2}{#3}];
	}

	\newcommand<>\ruler[3][]{%
		\draw#4[#1,ruler compass/ruler={#2}{#3}];
	}

	\newcommand<>\point[4][]{%
		\path#5 [name intersections={use=#2 and #3}] (intersection-#4) node[ruler compass/point,#1];
	}

\else

	\tikzset{
		alt if exist/.code args={#1#2#3}{%
				\pgfkeysalso{#2}%
			},
		onslide/.code args={<#1>#2}{%
				\pgfkeysalso{#2}%
			},
		intersection/save/.code={%
				\begingroup
				\tikz@intersect@path@names@parse#1\tikz@stop
				\protected@write\pgfutil@auxout{}{%
					\string\global\string\@namedef{path@\tikz@intersect@path@a}{\the\beamer@slideinframe}%
					\string\global\string\@namedef{path@\tikz@intersect@path@b}{\the\beamer@slideinframe}%
				}%
				\endgroup
			}
	}

	\newcommand\compass[2]{%
		\draw[ruler compass/compass={#1}{#2}];
	}

	\newcommand\ruler[2]{%
		\draw[ruler compass/ruler={#1}{#2}];
	}

	\newcommand\point[4][]{%
		\path [name intersections={use=#2 and #3}] (intersection-#4) node[ruler compass/point,#1];
	}

\fi

\tikzset{
	intersection/use/.style={%
			of=#1,
			save=#1,
		},
	circle through/.style={
			to path={
					\pgfextra{
						\tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
						\pgf@xa=\pgf@x
						\pgf@ya=\pgf@y
						\tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
						\pgfmathsetmacro\rc@radius{veclen(\pgf@x - \pgf@xa,\pgf@y - \pgf@ya)}%
					}
					circle[radius=\rc@radius pt] (\tikztotarget)
				}
		},
	arc flip/.is if=
	rc@fliparc,
	centred arc to/.code 2 args={%
			\tikz@scan@one@point\pgfutil@firstofone(#1)\relax
			\pgfmathsetmacro\rc@radius{veclen(\tikz@lastx-\pgf@x,\tikz@lasty-\pgf@y)}%
			\pgfmathsetmacro\rc@sangle{atan2(\tikz@lasty - \pgf@y,\tikz@lastx - \pgf@x)}%
			\pgf@xa=\pgf@x
			\pgf@ya=\pgf@y
			\tikz@scan@one@point\pgfutil@firstofone(#2)\relax
			\pgfmathsetmacro\rc@eangle{atan2(\pgf@y - \pgf@ya,\pgf@x - \pgf@xa)}%
			\pgfmathsetmacro\rc@eangle{\rc@eangle < \rc@sangle ? \rc@eangle +       360 : \rc@eangle}%
			\ifrc@fliparc
				\pgfmathsetmacro\rc@eangle{\rc@eangle - 360}%
			\fi
			\pgfkeysalso{start angle=\rc@sangle, end angle=\rc@eangle, radius=\rc@radius pt}
		},
	ruler compass/.is family,
	ruler compass/.cd,
	construction in use/.style={
			draw=blue
		},
	construction not in use/.style={
			draw=gray!75,
		},
	compass/.style 2 args={
			alt if exist={c-#1-#2}{
					ruler compass/construction in use/.try,
				}{
					ruler compass/construction not in use/.try
				},
			name path=c-#1-#2,
			ruler compass/every construction path/.try,
			ruler compass/every compass/.try,
			insert path={
					(#1) to[circle through] (#2)
					node[name=c-#1-#2-centre,ruler compass/aux point={#1}]
					node[name=c-#1-#2-rim,ruler compass/aux point={#2}]
				},
		},
	ruler/.style 2 args={
			overlay,
			alt if exist={r-#1-#2}{
					ruler compass/construction in use/.try
				}{
					ruler compass/construction not in use/.try
				},
			name path=r-#1-#2,
			ruler compass/every construction path/.try,
			ruler compass/every ruler/.try,
			insert path={
					($(#1)!\pgfkeysvalueof{/tikz/ruler compass/ruler length}!(#2)$) -- ($(#2)!\pgfkeysvalueof{/tikz/ruler compass/ruler length}!(#1)$)
					node[name=r-#1-#2-start,ruler compass/aux point={#1}]
					node[name=r-#1-#2-end,ruler compass/aux point={#2}]
				},
		},
	ruler length/.initial=20,
	aux point/.style={
			circle,
			minimum width=4mm,
			onslide=<.|handout:0>{draw=red},
			node contents={},
			at={(#1)},
			ruler compass/every aux point/.try
		},
	point/.style={
			ruler compass/name it,
			coordinate,
			node contents={},
			ruler compass/every point/.try,
			insert path={
					node[
							fill=#1,
							circle,
							minimum width=1mm,
							inner sep=0mm,
							reset label anchor,
							anchor=center,
							node contents={}
						]
				}
		},
	name it/.code={%
			\ifx\tikz@fig@name\pgfutil@empty
				\stepcounter{pointlabels}%
				\pgfkeysalso{name=\alphalph{\value{pointlabels}}}%
				\ifrc@draft
					\pgfkeysalso{label={[ruler compass/draft label/.try]\alphalph{\value{pointlabels}}}}%
				\fi
			\fi
		},
	point/.default=black,
}

\newcounter{jumping}
\resetcounteronoverlays{jumping}
\def\rc@scale{1}

\def\jump@setbb#1#2#3{%
	\@ifundefined{jump@#1@maxbb}{%
		\expandafter\gdef\csname jump@#1@maxbb\endcsname{#3}%
	}{%
		\csname jump@#1@maxbb\endcsname
		\pgf@xa=\pgf@x
		\pgf@ya=\pgf@y
		#3
		\pgfmathsetlength\pgf@x{max(\pgf@x,\pgf@xa)}%
		\pgfmathsetlength\pgf@y{max(\pgf@y,\pgf@ya)}%
		\expandafter\xdef\csname jump@#1@maxbb\endcsname{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
	}
	\@ifundefined{jump@#1@minbb}{%
		\expandafter\gdef\csname jump@#1@minbb\endcsname{#2}%
	}{%
		\csname jump@#1@minbb\endcsname
		\pgf@xa=\pgf@x
		\pgf@ya=\pgf@y
		#2
		\pgfmathsetlength\pgf@x{min(\pgf@x,\pgf@xa)}%
		\pgfmathsetlength\pgf@y{min(\pgf@y,\pgf@ya)}%
		\expandafter\xdef\csname jump@#1@minbb\endcsname{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
	}
}

\tikzset{
	stop jumping/.style={
			execute at end picture={%
					\stepcounter{jumping}%
					\pgfmathsetlength\pgf@xa{\pgf@picminx/\rc@scale}%
					\pgfmathsetlength\pgf@ya{\pgf@picminy/\rc@scale}%
					\pgfmathsetlength\pgf@xb{\pgf@picmaxx/\rc@scale}%
					\pgfmathsetlength\pgf@yb{\pgf@picmaxy/\rc@scale}%
					\immediate\write\pgfutil@auxout{%
						\noexpand\jump@setbb{\the\value{jumping}}{\noexpand\pgfpoint{\the\pgf@xa}{\the\pgf@ya}}{\noexpand\pgfpoint{\the\pgf@xb}{\the\pgf@yb}}
					},
					\csname jump@\the\value{jumping}@maxbb\endcsname
					\path (\the\pgf@x,\the\pgf@y);
					\csname jump@\the\value{jumping}@minbb\endcsname
					\path (\the\pgf@x,\the\pgf@y);
				},
		},
	max size/.code 2 args={%
			\addtocounter{jumping}{1}%
			\pgfutil@ifundefined{jump@\the\value{jumping}@maxbb}{}{%
				\csname jump@\the\value{jumping}@maxbb\endcsname
				\pgf@xa=\pgf@x
				\pgf@ya=\pgf@y
				\csname jump@\the\value{jumping}@minbb\endcsname
				\advance\pgf@xa by -\pgf@x
				\advance\pgf@ya by -\pgf@y
				\pgfmathsetmacro\rc@xratio{\pgf@xa > #1 ? \pgf@xa/#1 : 1}%
				\pgfmathsetmacro\rc@yratio{\pgf@ya > #2 ? \pgf@ya/#2 : 1}%
				\pgfmathsetmacro\rc@scale{1/max(\rc@xratio,\rc@yratio)}%
				\pgfkeysalso{scale=\rc@scale}%
			}
			\addtocounter{jumping}{-1}%
		}
}

\tikzset{
	on layer/.code={
			\pgfonlayer{#1}\begingroup
			\aftergroup\endpgfonlayer
			\aftergroup\endgroup
		},
	node on layer/.code={
			\gdef\node@@on@layer{%
				\setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}
			\aftergroup\node@on@layer
		},
	reset label anchor/.code={%
			\let\tikz@auto@anchor=\pgfutil@empty
			\def\tikz@anchor{#1}
		},
	reset label anchor/.default=center
}

\def\node@on@layer{\aftergroup\node@@on@layer}

\endinput
